/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_components/zhiqim_manager.htm
 *
 * Zhiqim Manager is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.manager;

import java.sql.Timestamp;
import java.util.List;

import org.zhiqim.kernel.Global;
import org.zhiqim.kernel.config.ItemType;
import org.zhiqim.kernel.model.codes.RSA;
import org.zhiqim.kernel.model.objects.SS;
import org.zhiqim.kernel.schedule.Day;
import org.zhiqim.kernel.schedule.Scheduler;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Bytes;
import org.zhiqim.kernel.util.Randoms;
import org.zhiqim.kernel.util.Resources;
import org.zhiqim.kernel.util.Sqls;
import org.zhiqim.kernel.util.Streams;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.manager.dao.ZmrParamDao;
import org.zhiqim.manager.dbo.ZmrAvatar;
import org.zhiqim.manager.dbo.ZmrDept;
import org.zhiqim.manager.dbo.ZmrMenu;
import org.zhiqim.manager.dbo.ZmrOperator;
import org.zhiqim.orm.ORM;

/**
 * 初始化引导类
 *
 * @version v1.0.0 @author zouzhigang 2015-5-28 新建与整理
 */
public class ZmrBootstrap extends ZmrBootstrapApi
{
    private static ZmrPassworder passworder;//管理台密码器
    
    /*******************************************************************************/
    //初始化
    /*******************************************************************************/
    
    @Override
    protected void initBefore() throws Exception
    {
        context.setAttribute(ZmrBootstrap.class, this);
        
        String zmrPassworder = context.getTopAttributeString(ZMR_PASSWORDER, ZMR_PASSWORDER_DEFAULT);
        Object instance = Global.newInstance(zmrPassworder);
        Asserts.asserts(instance instanceof ZmrPassworder, "上下文环境[%s]的密码器配置[zmr.passworder]不是ZmrPassworder或子类", context.getContextName());
        
        passworder = (ZmrPassworder)instance;
    }
    
    @Override
    protected void initAfter() throws Exception
    {
        initMenu();
        initAvatar();
        initParam();
        initDept();
        initOperator();
        
        //设置主题默认值
        context.setAttribute(ZMR_THEME_INDEX, ZmrParamDao.getThemeIndex());
        context.setAttribute(ZMR_THEME_MAIN, ZmrParamDao.getThemeMain());
        
        //增加删除日志任务
        Scheduler scheduler = Global.getc(Scheduler.class);
        scheduler.addTask(new Day(new ZmrTask(), 5, 5, 5));
    }
    
    /** 初始化菜单 */
    private void initMenu() throws Exception
    {
        if (ORM.table().count(ZmrMenu.class) > 0)
            return;
        
        String path = context.getAttributeString(ZMR_MENU_SQL);
        if (Validates.isEmpty(path))
            return;
        
        String sqls = context.getResourceString(path);
        if (sqls == null)
            return;
        
        List<String> sqlList = Sqls.toSqlList(sqls);
        if (sqlList.isEmpty())
            return;
        
        ORM.sql().execute(sqlList);
    }
    
    /** 初始化参数 */
    private void initParam() throws Exception
    {
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_THEME_INDEX,             "00_default",                  1,  ItemType.PROTECTED, "首页主题（在首页主题中修改）");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_THEME_MAIN,              "00_default",                  2,  ItemType.PROTECTED, "主页主题（在主页主题中修改）");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_THEME_FRAME,             "false",                       3,  ItemType.PUBLIC,    "主题是否使用iframe风格");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_HAS_MANAGE_LOGIN,        "false",                       4,  ItemType.PUBLIC,    "是否使用管理页登录退出功能");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_HAS_VERIFICATION_CODE,   "false",                       5,  ItemType.PUBLIC,    "是否需要验证码");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_HAS_REMEMBER_CODE,       "true",                        6,  ItemType.PUBLIC,    "是否显示记住账号");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_HAS_REMEMBER_PASS,       "false",                       7,  ItemType.PUBLIC,    "是否显示记住密码");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_CHK_CLOSE_SUPER_ADMIN,   "true",                        8,  ItemType.PUBLIC,    "是否任务检查需要关闭超级管理员");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_REMAIN_LOG_DAY,          "90",                          9,  ItemType.PUBLIC,    "保留操作员日志天数");
        
        if (!ZmrParamDao.hasParam(ZMR_NAME, ZMR_PUBLIC_KEY) || !ZmrParamDao.hasParam(ZMR_NAME, ZMR_PRIVATE_KEY))
        {//密钥没成对
            SS keys = RSA.buildKeyPair();
            
            ZmrParamDao.replaceParam(ZMR_NAME, ZMR_PUBLIC_KEY,              keys.key(),                       10, ItemType.PRIVATE,   "随机生成的公钥");
            ZmrParamDao.replaceParam(ZMR_NAME, ZMR_PRIVATE_KEY,             keys.value(),                     11, ItemType.PRIVATE,   "随机生成的私钥");
        }
        
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_MAIN_URL,                "/${zhiqim_manager}/main.htm", 12, ItemType.PUBLIC,    "指定登录之后的主页地址，为空取标准主页地址");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_CDN_PATH,                "",                            13, ItemType.PUBLIC,    "如果CDN路径不为空，JS文件优先取CDN路径");
        ZmrParamDao.addParamIfNotExists(ZMR_NAME, ZMR_OPERATOR_DEPT_ALL_RULE,  "true",                        14, ItemType.PUBLIC,    "操作员权限是否继承上级部门权限");
    }

    /** 初始化头像 */
    private void initAvatar() throws Exception
    {
        if (ORM.table().count(ZmrAvatar.class) > 0)
            return;
        
        long avatarId = ID13;
        List<String> avatarNameList = Resources.getResourceNameList(ZmrBootstrap.class, AVATAR_PREFIX);
        for (String avatarName : avatarNameList)
        {
            byte[] data = Streams.getBytesClassPath(ZmrBootstrap.class, AVATAR_PREFIX + avatarName);
            
            byte[]  bytes50 = Bytes.resizePNG(data, 50, 50);
            byte[]  bytes100 = Bytes.resizePNG(data, 100, 100);
            byte[]  bytes150 = Bytes.resizePNG(data, 150, 150);
            
            ZmrAvatar avatar = new ZmrAvatar();
            avatar.setAvatarId(avatarId++);
            avatar.setAvatarType(0);
            avatar.setAvatarTime(System.currentTimeMillis());
            avatar.setAvatar50(bytes50);
            avatar.setAvatar100(bytes100);
            avatar.setAvatar150(bytes150);
            
            ORM.table().insert(avatar);
        }
    }
    
    /** 初始化部门 */
    private void initDept() throws Exception
    {
        if (ORM.table().count(ZmrDept.class) > 0)
            return;
        
        ZmrDept dept = new ZmrDept();
        dept.setParentId(0);
        dept.setDeptId(ID13);
        dept.setDeptName("湖南知启蒙科技创业中心");
        dept.setDeptStatus(0);
        dept.setDeptLevel(0);
        dept.setDeptParentAll("0");
        
        ORM.table().insert(dept);
    }
    
    /** 初始操作员，使用操作员独立数据库 */
    private void initOperator() throws Exception
    {
        int count = ORM.table().count(ZmrOperator.class);
        if (count > 0)
            return;
        
        Timestamp timestamp = Sqls.nowTimestamp();
        String passSalt = Randoms.lettersDigitsSecure(64);
        
        ZmrOperator operator = new ZmrOperator();
        operator.setOperatorCode(Z_NAME);
        operator.setOperatorPass(passworder.encode(Z_NAME, ZMR_PASSWORD, passSalt));
        operator.setOperatorPassSalt(passSalt);
        operator.setOperatorStatus(0);
        operator.setOperatorType(0);
        operator.setOperatorAvatar(ID13);
        operator.setOperatorName("超级管理员");
        operator.setOperatorCreated(timestamp);
        operator.setOperatorModified(timestamp);
        
        ORM.table().replace(operator);
    }
    
    /*******************************************************************************/
    //获取管理台密码器
    /*******************************************************************************/
    
    /** 获取密码器 */
    public static ZmrPassworder getPassworder()
    {
        return passworder;
    }
}
